package cate.game.role.farm.guildFairyland;

import cate.common.table.d.GDFight;
import cate.common.table.d.GDFunc;
import cate.common.table.d.GDGuild;
import cate.common.table.d.GDOperation;
import cate.common.table.guild.fairyland.base.GuildFairyBaseRow;
import cate.common.util.GameResult;
import cate.game.play.part.FightSide;
import cate.game.play.proce.play.PlayPO;
import cate.game.res.MixRes;
import cate.game.res.MixResAdder;
import cate.game.res.Pair;
import cate.game.role.Role;
import cate.game.role.farm.AbstractFarm;
import cate.game.role.farm.PlayTimes;
import cate.game.role.farm.guildFairyland.msg.GuildFairyChallengeResp;
import cate.game.role.farm.guildFairyland.msg.GuildFairyInfoResp;
import cate.game.role.res.guild.po.GuildPO;
import easy.java.dev.note.NoteClass;
import easy.java.dev.note.NoteField;
import easy.java.practice.errorcode.EcResult;

import java.util.List;

@NoteClass("公会秘境-个人挑战数据")
public class MyGuildFairylandPO extends AbstractFarm {
    @NoteField("BOSS开始时间")
    public long bossStartTime;
    @NoteField("玩法次数")
    public PlayTimes playTimes;

    @Override
    public int getFuncId() {
        return GDFunc.GuildFunc.FAIRYLAND;
    }

    @Override
    public void onAfterOpen() {

    }

    @Override
    public int getFightFuncId() {
        return GDFunc.GuildFunc.FAIRYLAND;
    }

    @Override
    public void initialize(Role role) {
        super.initialize(role);
        if (playTimes == null) {
            playTimes = new PlayTimes();
        }
        playTimes.initialize();
    }

    @Override
    public void onEnter() {
        checkState();
    }

    /**
     * 检测玩法状态
     */
    public void checkState() {
        GuildPO guildPO = role.getRes().guild.getGuild();
        if (guildPO == null) {
            return;
        }
        if (guildPO.fairyland.bossStartTime != bossStartTime) {
            bossStartTime = guildPO.fairyland.bossStartTime;
            playTimes.reset();
        }
    }

    /**
     * 同布消息到前端
     */
    public void noticeUpdate() {
        role.sendNow(new GuildFairyInfoResp(role));
    }

    /**
     * 开启BOSS
     *
     * @param bossType BOSS类型
     * @return 开启结果
     */
    public EcResult<Void> startBoss(int bossType) {
        EcResult<Void> r = new EcResult<>();
        if (!isOpen()) {
            return r.fail("功能未开启");
        }
        GuildPO guildPO = role.getRes().guild.getGuild();
        if (guildPO == null) {
            return r.fail("未加入公会");
        }
        if (role.getRes().guild.performance.position < GDGuild.position.VICE_PRESIDENT) {
            return r.fail("仅会长和副会长可开启秘境");
        }
        r = guildPO.fairyland.startBoss(bossType);
        if (!r.ok()) {
            return r;
        }
//        noticeUpdate();
        return r.success();
    }

    /**
     * 发起挑战
     *
     * @return 挑战结果
     */
    public EcResult<Void> challenge() {
        EcResult<Void> r = new EcResult<>();
        GuildPO guildPO = role.getRes().guild.getGuild();
        if (guildPO == null) {
            return r.fail("未加入公会");
        }
        if (role.getRes().guild.joinTime != 0
                && System.currentTimeMillis() - role.getRes().guild.joinTime < GDGuild.Fairyland.NEW_MEMBER_COLD) {
            return r.fail("加入公会24小时之内不能挑战");
        }
        if (guildPO.fairyland.openingBossType == 0) {
            return r.fail("公会秘境未开启");
        }
        GameResult<Void> r_play = playTimes.available(role, getFuncId());
        if (!r_play.ok()) {
            return r.fail(r_play.code, r_play.message);
        }
        r = guildPO.fairyland.tryChallenge(role);
        if (!r.ok()) {
            return r;
        }
        playTimes.added();
        noticeUpdate();
        return r.success();
    }

    /**
     * 发起BOSS挑战
     *
     * @param tid   BOSS基础配置ID
     * @param buffs BOSS随机BUFF列表
     * @param curHp BOSS当前血量
     * @return 挑战结果 携带FTC
     */
    public EcResult<Pair<GuildFairylandFTC, PlayPO>> startFight(int tid, List<Integer> buffs, long curHp) {
        EcResult<Pair<GuildFairylandFTC, PlayPO>> r = new EcResult<>();
        GuildFairyBaseRow baseRow = role.getGame().table.guildFairyland.base.get(tid);
        if (baseRow == null) {
            return r.fail("BOSS基础配置不存在");
        }
        EcResult<FightSide> fsr = role.getGame().fight.side.createFightSideByCode(GDFight.Team.B, baseRow.insCode);
        if (!fsr.ok()) {
            return r.fail(fsr.message);
        }
        GuildFairylandFTC context = new GuildFairylandFTC(role, tid);

        context.funcId = GDFunc.GuildFunc.FAIRYLAND;
        context.setPositionApply(GDFunc.ADVENTURE);
        context.param.sideB.hpExtend.recordByHeroTid(fsr.data.ps.hs.get(0).hero.tid, curHp / (double) baseRow.hp);
        buffs.forEach(buffSkill -> context.param.sideB.skillAppend.addTeamSkill(buffSkill));

        context.playStory.level = tid;
        EcResult<PlayPO> fightRes = role.getGame().play.startByRole(role, context, fsr.data);
        if (!fightRes.ok()) {
            return r.fail(fightRes.message);
        }
        r.data = new Pair<>(context, fightRes.data);
        this.fighting = true;
        return r.success();
    }

    /**
     * 挑战结算
     *
     * @param tid    BOSS配置ID
     * @param killed 是否击杀
     * @param damage 伤害
     */
    public void onChallengeEnd(int tid, boolean killed, long damage) {
        GuildFairyBaseRow baseRow = role.getGame().table.guildFairyland.base.get(tid);
        if (baseRow == null) {
            return;
        }
        // 发放挑战奖励
        new MixResAdder().setRes(baseRow.challengeReward)
                .setSendMailWhenFull(true)
                .setDialogReward(false)
                .setOperation(GDOperation.GUILD_FAIRYLAND_CHALLENGE)
                .setOperationSub(tid)
                .exe(role);
        role.sendNow(new GuildFairyChallengeResp(killed, damage, new MixRes(baseRow.challengeReward)));
    }
}
